﻿using System.Collections.Generic;
using UnityEngine;

public class CameraLevel2 : CameraLevel, Camera3DLevel
{
    
    [System.Serializable]
    public struct GateEnemyConfig
    {
        public Vector2 position;
        public GameObject prefab;
    }
    [System.Serializable]
    public struct GateConfig
    {
        public GateEnemyConfig[] enemies;
    }

    private SeqAction gateAction = new() { beginWaitTime = 1f };
    private SeqAction gateFadeinAction = new() { beginWaitTime = 2f, intervalTime = 16f / 60f };
    private SeqAction coreDestroyAction = new() { };
    public bool electricField = true;
    private GameObject electricFieldObj;
    private Transform residualGateObj;

    private SpriteRenderer mainSR;
    private Material initMat;
    private Sprite[] passagewaySprites;
    private int passagewayIndex = 0;

    private GameObject[] frontgoundMaskObjs;
    private GameObject boomPrefab;

    private EnemyGenerator[] enemyGens;

    private GameObject gatesObj;
    private GameObject bossGateObj;
    private GameObject bossBackgroundObj;
    private GameObject gridGround;
    private GameObject grid3DGround;
    private GameObject gridWall;
    private GameObject gridBossGround;
    private GameObject bossObj;
    private bool isBossDie=false;
    private SeqAction bossDieAction=new (){};
    private bool isBossGate;

    private GameObject leftElevatorObj;
    private GameObject rightElevatorObj;

    [Tooltip("剧本动作")]
    public SeqAction scenarioWait = new() { beginWaitTime = 2f };



    private FadeInOut.FadeInOutData[] fadeInData ={
        new(){
            cilpUnMatch=true,
            targetColors =new string[]{"#000000",},
            replaceColors=new string[] {"#000000",},
        },
        new(){
            cilpUnMatch=true,
            targetColors =new string[]{"#e0a0c0",},
            replaceColors=new string[] {"#a04000",},
        },
        new(){
            cilpUnMatch=true,
            targetColors =new string[]{"#e0a0c0","#FFFFFF"},
            replaceColors=new string[] {"#e06000","#808080"},
        },
        new(){
            cilpUnMatch=false,
            targetColors =new string[]{"#000000",},
            replaceColors=new string[] {"#000000",},
        },
    };

    private GateConfig[] gateConfig;
    private int gateIndex=4;
    private void Awake()
    {
        base.Init();
        gatesObj=Utility.GetObjectWithName("Gates");
        bossGateObj=Utility.GetObjectWithName("BossGate");
        electricFieldObj = Utility.GetObjectWithName("电网");
        gridGround=Utility.GetObjectWithName("地面");
        grid3DGround=Utility.GetObjectWithName("3D地面");
        gridWall=Utility.GetObjectWithName("墙");
        gridBossGround=Utility.GetObjectWithName("Boss地面");
        bossBackgroundObj=Utility.GetObjectWithName("Boss底图");
        bossObj=Utility.GetObjectWithName("敌-第二关-Boss");
        leftElevatorObj=Utility.GetObjectWithName("Boss-电梯-左");
        rightElevatorObj=Utility.GetObjectWithName("Boss-电梯-右");

        mainSR = Utility.GetObjectWithName("中").GetComponent<SpriteRenderer>();
        residualGateObj = Utility.GetObjectWithName("破").transform;
        gateFadeinAction.done = true;
        passagewaySprites = new Sprite[]{
            ResourcesPool.Sprites["魂-第二关-中"],
            ResourcesPool.Sprites["魂-第二关-通道1"],
            ResourcesPool.Sprites["魂-第二关-通道2"],
            ResourcesPool.Sprites["魂-第二关-通道3"],
        };
        residualGateObj.gameObject.SetActive(false);
        initMat = FadeInOut.GetFadeMaterial(fadeInData[0]);
        frontgoundMaskObjs=new GameObject[]{
            Utility.GetObjectWithName("中-前景遮挡-左"),
            Utility.GetObjectWithName("中-前景遮挡-右"),
        };
        boomPrefab=Constant.Prefabs.EnemyBoom1.Load();


        gateConfig = new GateConfig[]{
            new GateConfig(){
                //第一道门
                enemies=new GateEnemyConfig[]{
                    new(){
                        prefab=Constant.Prefabs.Enemy3DCoreSmall.Load(),
                        position=new(8f,8f),
                    },
                }
            },
            new GateConfig(){
                //第二道门
                enemies=new GateEnemyConfig[]{
                    new(){
                        prefab=Constant.Prefabs.Enemy3DCoreSmall.Load(),
                        position=new(6.5f,8f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(9.5f,8f),
                    },
                }
            },
            new GateConfig(){
                //第三道门
                enemies=new GateEnemyConfig[]{
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(6.5f,8f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(9.5f,8f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DCoreSmall.Load(),
                        position=new(8f,7.5f),
                    },
                }
            },
            new GateConfig(){
                //第四道门
                enemies=new GateEnemyConfig[]{
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(8f,9f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DCoreSmall.Load(),
                        position=new(8f,8f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DRollLauncher.Load(),
                        position=new(8f,7f),
                    },
                }
            },
            new GateConfig(){
                //第五道门
                enemies=new GateEnemyConfig[]{
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(8f,9.5f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(6.5f,8f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DCoreBig.Load(),
                        position=new(8f,8f),
                    },
                    new(){
                        prefab=Constant.Prefabs.Enemy3DTurretSmall.Load(),
                        position=new(9.5f,8f),
                    },
                }
            },
        };
    }
    private void Start()
    {
        // StartGates();
        StartBossGate();
    }

    private void FixedUpdate()
    {
        UpdateBeginPerformance();
        if(isBossGate){
            UpdateBossCoreDestroy();
            UpdateBossDie();
        }else{
            UpdateElectricField();
            UpdateCoreDestroy();
        }
        UpdateGateFadein();
    }

    private void UpdateElectricField()
    {
        if (electricFieldObj.activeInHierarchy != electricField)
        {
            electricFieldObj.SetActive(electricField);
        }
    }
    private void UpdateGateFadein()
    {
        gateFadeinAction.Update((SeqAction seq) =>
        {
            if (seq.seqNo > fadeInData.Length)
            {
                seq.done = true;
                StartEnemy();
            }
            else
            {
                Material mat = FadeInOut.GetFadeMaterial(fadeInData[seq.seqNo - 1]);
                GetFadeInSR().Action((SpriteRenderer sr) =>
                {
                    sr.material = mat;
                });
            }
        });
    }

    private void UpdateCoreDestroy()
    {
        if(gateFadeinAction.done){
            coreDestroyAction.Update((SeqAction seq) =>
            {
                if(seq.IsFirstAction()){
                    seq.PropertyBool.Add("coreDestroy",false);
                    if(seq.PropertyFloat.ContainsKey("destroyTime")){
                        seq.PropertyFloat.Remove("destroyTime");
                        seq.PropertyInteger.Remove("boomCount");
                    }
                }
                Enemy3DCore aliveCore = GameObject.FindObjectsOfType<Enemy3DCore>().FindWith((Enemy3DCore enemy) =>
                {
                    return !enemy.IsDie();
                });
                bool coreDestroy = seq.PropertyBool["coreDestroy"];
                if (!aliveCore && !coreDestroy)
                {
                    DestroyAllEnemyOfGate();
                    seq.PropertyBool["coreDestroy"] = true;
                    if (!seq.PropertyFloat.ContainsKey("destroyTime"))
                    {
                        seq.PropertyFloat.Add("destroyTime", Time.time);
                        seq.PropertyInteger.Add("boomCount", 0);
                    }
                }
                if(coreDestroy){
                    float destroyTime=seq.PropertyFloat["destroyTime"];
                    float destroyDurationTime=Time.time-destroyTime;
                    int boomCount=seq.PropertyInteger["boomCount"];
                    int index=Mathf.FloorToInt(destroyDurationTime/0.3f);
                    if(index>boomCount){
                        Rect boomRect=new Rect(96f/16,112f/16f,64f/16,48f/16f);
                        for(int i=boomCount;i<index;i++){
                            float x=Random.Range(boomRect.min.x,boomRect.max.x);
                            float y=Random.Range(boomRect.min.y,boomRect.max.y);
                            Instantiate(boomPrefab,new Vector2(x,y),Quaternion.identity);
                            Constant.Sounds.EnemyDeath2.PlayOneShot();
                        }
                        boomCount+=1;

                        if(boomCount>3){
                            residualGateObj.gameObject.SetActive(true);
                            electricField = false;
                            frontgoundMaskObjs.Action((GameObject go)=>{
                                go.SetActive(false);
                            });
                            seq.done = true;
                        }else{
                            seq.PropertyInteger["boomCount"]=boomCount;
                        }
                    }

                }
            });
        }
    }

    private void UpdateBossCoreDestroy()
    {
        if(gateFadeinAction.done){
            coreDestroyAction.Update((SeqAction seq) =>
            {
                Enemy3DCore aliveCore = bossGateObj.GetComponentsInChildren<Enemy3DCore>().FindWith((Enemy3DCore enemy) =>
                {
                    return !enemy.IsDie();
                });
                if (!aliveCore)
                {
                    seq.done=true;
                    StartBoss();
                }
            });
        }
    }

    public override bool Is3DLevel()
    {
        return true && !isBossDie;
    }
    public override bool Is3DBossLevel()
    {
        return isBossGate && !isBossDie;
    }

    private void DestroyAllEnemyOfGate(){
        enemyGens.Action((EnemyGenerator gen)=>{
            gen.StopWork();
        });
        GameObject.FindObjectsOfType<EnemyBase>().Action((EnemyBase enemy) =>
        {
            enemy.DieAndDestroy();
        });
    }
    private void StartGate(int index)
    {
        frontgoundMaskObjs.Action((GameObject go)=>{
            go.SetActive(false);
        });

        GateConfig config=gateConfig[index];
        config.enemies.Action((GateEnemyConfig enemyConfig)=>{
            Instantiate(enemyConfig.prefab,enemyConfig.position,Quaternion.identity);
        });

        electricField = true;
        GetFadeInSR().Action((SpriteRenderer sr) =>
        {
            sr.material = initMat;
        });
        gateFadeinAction.Clear();
        coreDestroyAction.Clear();

        enemyGens=GameObject.FindObjectsOfType<EnemyGenerator>()
        .Action((EnemyGenerator gen)=>{
            gen.StopWork();
        })
        .Filter((EnemyGenerator gen) => {
            return gen.transform.parent.name.Equals("Gate"+(gateIndex+1));
        }).ToArray();

        // enemyGens = GameObject.FindObjectsOfType<EnemyGenerator>();


    }

    private void StartEnemy()
    {
        frontgoundMaskObjs.Action((GameObject go)=>{
            go.SetActive(true);
        });

        GameObject.FindObjectsOfType<EnemyBase>().Action((EnemyBase enemy) =>
        {
            enemy.Run(); 
        });
        enemyGens.Action((EnemyGenerator gen) =>
        {
            gen.StartWork();
        });
        Test();

    }
    private SpriteRenderer[] GetFadeInSR()
    {
        List<SpriteRenderer> ret = new();
        if(isBossGate){
            if(bossBackgroundObj.TryGetComponent(out SpriteRenderer sr)){
                ret.Add(sr);
            }
        }else{
            ret.Add(mainSR);
            electricFieldObj.GetComponentsInChildren<SpriteRenderer>().Action((SpriteRenderer sr) =>
            {
                ret.Add(sr);
            });
        }
        GameObject.FindObjectsOfType<EnemyBase>().Action((EnemyBase enemy) =>
        {
            enemy.GetComponentsInChildren<SpriteRenderer>().Action((SpriteRenderer sr) =>
            {
                ret.Add(sr);
            });
            // ret.Add(enemy.GetComponent<SpriteRenderer>());
        });
        return ret.ToArray();
    }
    public override bool HasElectricField()
    {
        return electricField;
    }

    public bool NextPassageway()
    {
        bool ret = false;
        passagewayIndex++;
        if (passagewayIndex >= passagewaySprites.Length)
        {
            passagewayIndex = 0;
            ret = true;
            gateIndex++;
            if(gateIndex>=gateConfig.Length){
                // gateIndex=0;
                StartBossGate();
            }else{
                StartGate(gateIndex);
            }
        }
        residualGateObj.gameObject.SetActive(false);
        mainSR.sprite = passagewaySprites[passagewayIndex];
        return ret;
    }

    public virtual Rect GetPlayerViewRect(){
        return new(32f, 48f, 192f, 41f);
    }
    public virtual Rect GetPlayerProstrateViewRect(){
        return  new(56f, 80f, 144f, 112f);
    }
    public virtual Rect GetEnemyViewRect(){
        return new(96f, 112f, 64f, 18f);
    }    

    private void Test(){
        GameObject obj=Utility.GetObjectWithName("敌-3D-滚筒");
        if(obj!=null){
            if(obj.TryGetComponent(out Enemy3DRoller roller)){
                roller.Run();
            }
        }
    }

    private void StartGates(){
        gatesObj.SetActive(true);
        bossGateObj.SetActive(false);
        gridGround.SetActive(true);
        grid3DGround.SetActive(true);
        gridBossGround.SetActive(false);
        gateIndex=0;
        isBossGate=false;
        StartGate(gateIndex);
    }
    private void StartBossGate(){
        gatesObj.SetActive(false);
        bossGateObj.SetActive(true);
        gridGround.SetActive(false);
        grid3DGround.SetActive(false);
        gridBossGround.SetActive(true);
        isBossGate=true;
        GetFadeInSR().Action((SpriteRenderer sr) =>
        {
            sr.material = initMat;
        });
        gateFadeinAction.Clear();
        coreDestroyAction.Clear();
        enemyGens=new EnemyGenerator[0];    
    }

    private void StartBoss(){
        bossObj.SetActive(true);
        if(bossObj.TryGetComponent(out EnemyBoss2Core boss)){
            boss.Run();
        }
    }

    public void UpdateBossDie(){
        if(bossObj==null){
            bossDieAction.Update((SeqAction seq)=>{
                if(seq.IsFirstAction()){
                    GameObject.FindObjectsOfType<EnemyBase>().Action((EnemyBase enemy)=>{
                        enemy.Die();
                    });
                    isBossDie=true;
                    GameObject.FindObjectsOfType<Player>().Action((Player player)=>{
                        player.RunScenario(this.ScenarioBossDie);
                    });
                    gridWall.SetActive(false);
                    backgroundSound.Stop();
                    Constant.Sounds.Victory.PlayOneShot();
                }
                Player notArrivedPlayer=GameObject.FindObjectsOfType<Player>().FindWith((Player player)=>{
                    bool notArrive=false;
                    if(player.GetLife()>0){
                        if(player.PlayerIdentity==PlayerContext.EnumPlayer.BillRizer){
                            notArrive=player.transform.position.x>0.75f;
                            if(!notArrive && !leftElevatorObj.activeInHierarchy){
                                leftElevatorObj.SetActive(true);
                            }
                        }else if(player.PlayerIdentity==PlayerContext.EnumPlayer.LanceBean){
                            notArrive=player.transform.position.x<15.25f;
                            if(!notArrive && !rightElevatorObj.activeInHierarchy){
                                rightElevatorObj.SetActive(true);
                            }
                        }
                    }
                    return notArrive;
                });

                if(notArrivedPlayer==null){
                    new GameObject[]{leftElevatorObj,rightElevatorObj}.Action((GameObject go)=>{
                        if(go.TryGetComponent(out Rigidbody2D rig)){
                            rig.velocity=Vector2.up*3f;
                        };
                    });
                    float y=Mathf.Max(leftElevatorObj.transform.position.y,rightElevatorObj.transform.position.y);
                    if(y>Camera.main.ViewportToWorldPoint(new Vector2(1,1)).y){
                        ScenceFinshed();
                    }
                }
            });
        }
    }

    public override int GetLevelNo()
    {
        return 2;
    }    


    private Player.ScenarioAction ScenarioBossDie(PlayerContext context){
        Player.ScenarioAction ret=new();
        ret.SetFloat(Player.KeyMapKey.Horizontal.ToString(), 0f);
        ret.SetBool(Player.KeyMapKey.Fire.ToString(), false);
        ret.SetBool(Player.KeyMapKey.Jump.ToString(), false);
        scenarioWait.Update((SeqAction seq) =>
        {
            Vector2 position = context.Position;
            if(context.PlayerIdentity==PlayerContext.EnumPlayer.BillRizer){
                if(position.x<=0.75f){
                    position.x=0.75f; 
                    context.Position=position;
                    ret.SetFloat(Player.KeyMapKey.Horizontal.ToString(), 0f);
                    context.LookAt=new Vector2(1,context.LookAt.y);
                }else{
                    ret.SetFloat(Player.KeyMapKey.Horizontal.ToString(), -1f);
                }
            }else if(context.PlayerIdentity==PlayerContext.EnumPlayer.LanceBean){
                if(position.x>=15.25f){
                    position.x=15.25f;
                    context.Position=position;
                    ret.SetFloat(Player.KeyMapKey.Horizontal.ToString(), 0f);
                    context.LookAt=new Vector2(-1,context.LookAt.y);
                }else{
                    ret.SetFloat(Player.KeyMapKey.Horizontal.ToString(), 1f);
                }
            }
        });
        return ret;
    }    
}
